home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / ausay / speak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  7.1 KB  |  328 lines

  1. /************************************************************************
  2. *                                    *
  3. *   Copyright 1990, Brown University, Providence, RI.            *
  4. *   Permission to use, copy, modify and distribute this software and    *
  5. *   its documentation for any purpose other than its incorporation    *
  6. *   into a commercial product, is hereby granted, provided that this    *
  7. *   copyright notice appears on all copies.                *
  8. *                                    *
  9. ************************************************************************/
  10. /************************************************************************
  11. *                                    *
  12. *    speak.c                                *
  13. *                                    *
  14. ************************************************************************/
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <sys/stat.h>
  18. #include <audio/audiolib.h>
  19. #include <audio/soundlib.h>
  20. #include <dirent.h>
  21. #include <fcntl.h>
  22. #include <errno.h>
  23. #include <stdio.h>
  24.  
  25. #define getwd(x)    getcwd(x, 1024)
  26.  
  27. static int    volume = 100;
  28.  
  29. #define VOL(volume)             (int)((1 << 16) * (volume) / 100)
  30.  
  31. /************************************************************************
  32. *                                    *
  33. *    type and array of phoneme audio samples                *
  34. *                                    *
  35. ************************************************************************/
  36. typedef struct phoneme_t
  37. {
  38.     int             size;
  39.     char           *data;
  40.     char        *fname;
  41.     Sound        sound_hdr;
  42. };
  43.  
  44. static struct phoneme_t phoneme[1024];
  45.  
  46. /************************************************************************
  47. *                                    *
  48. *    names of known phonemes                        *
  49. *                                    *
  50. ************************************************************************/
  51. static
  52. char           *phoneme_name[] = {
  53.     "IY", "EY", "AE", "AO", "UH",
  54.     "ER", "AH", "AW", "IH", "EH",
  55.     "AA", "OW", "UW", "AX", "AY",
  56.     "OY", "YU", "p", "t", "k", "f",
  57.     "TH", "s", "SH", "HH", "n",
  58.     "l", "y", "CH", "WH", "b",
  59.     "d", "g", "v", "DH", "z",
  60.     "ZH", "m", "NG", "w", "r", "j",
  61.     (char *) 0
  62. };
  63.  
  64. extern FILE    *In_file;    /* from parse.c */
  65. extern char    *sys_errlist[];
  66.  
  67. static char    *buffer;
  68. static int      curfd;
  69.  
  70. AuServer       *aud;
  71.  
  72. speak_load_samples(dir)
  73. char    *dir;
  74. {
  75.     register        i, k, rv;
  76.     char           *cp;
  77.     char            cwd[1024];
  78.     DIR            *dirp;
  79.     struct dirent  *dp;
  80.     struct stat     st;
  81.     Sound           ah;
  82.     static char    tmp[BUFSIZ];
  83.  
  84.     if ((dirp = opendir(dir)) == 0)
  85.         return fatal(0, "can't open directory %s", dir);
  86.  
  87.     (void) getwd(cwd);
  88.     if (chdir(dir))
  89.         return fatal(0, dir);
  90.  
  91.     while (dp = readdir(dirp))
  92.     {
  93.         for (cp = phoneme_name[i = 0];
  94.              cp && strcmp(dp->d_name, cp) != 0;
  95.              cp = phoneme_name[++i]);
  96.         if (cp == (char *) 0)
  97.             continue;
  98.  
  99.         i = ch_to_code(&cp);
  100.  
  101. #ifdef USE_PLAYDATA
  102.         if ((ah = SoundOpenFileForReading(dp->d_name)) == (Sound) 0)
  103.             return fatal(0, dp->d_name);
  104.         if (phoneme[i].data)
  105.             free(phoneme[i].data);
  106.         phoneme[i].size = SoundNumBytes(ah);
  107.         phoneme[i].sound_hdr = ah;
  108.  
  109.         if ((phoneme[i].data = (char *) malloc(phoneme[i].size)) == 0)
  110.             return fatal(0, "malloc returned zero");
  111.  
  112.         SoundReadFile (phoneme[i].data, phoneme[i].size, phoneme[i].sound_hdr);
  113.  
  114.         SoundCloseFile (phoneme[i].sound_hdr);
  115. #else
  116.         strcpy (tmp, dir);
  117.         strcat (tmp, "/");
  118.         strcat (tmp, dp->d_name);
  119.         if ((phoneme[i].fname = malloc (strlen (tmp) + 1)) == 0)
  120.             return fatal(0, "malloc returned zero");
  121.         strcpy(phoneme[i].fname, tmp);
  122. #endif
  123.  
  124.     }
  125.     closedir(dirp);
  126.  
  127.     for (cp = phoneme_name[i = 0]; cp; cp = phoneme_name[++i])
  128.     {
  129.         k = ch_to_code(&cp);
  130. #ifdef USE_PLAYDATA
  131.         if (phoneme[k].size == 0)
  132.             return fatal(0, "zero length phoneme '%s'", phoneme_name[i]);
  133. #else
  134.         if (phoneme[k].fname == NULL)
  135.             return fatal(0, "No filename for phoneme '%s'", phoneme_name[i]);
  136.  
  137. #endif
  138.     }
  139.  
  140.     if (chdir(cwd))
  141.         return fatal(0, cwd);
  142.  
  143.     return 0;
  144. }
  145.  
  146. speak_string(str)
  147.     char           *str;
  148. {
  149.     buffer = str;
  150.     xlate_file();        /* hook into eng_to_phoneme code */
  151.     buffer = (char *) 0;
  152.  
  153.     return 0;
  154. }
  155.  
  156. speak_volume(vol)
  157.     int          vol;
  158. {
  159.     volume = vol;
  160. }
  161.  
  162. speak_close(fd)
  163.     int             fd;
  164. {
  165.     close(fd);
  166.  
  167.     return 0;
  168. }
  169.  
  170. hacked_getc(fp)
  171.     FILE           *fp;
  172. {
  173.     static          ix;
  174.  
  175.     if (In_file)
  176.         return getc(fp);
  177.  
  178.     if (buffer[ix] == 0)
  179.     {
  180.         ix = 0;
  181.         return EOF;
  182.     }
  183.     else
  184.         return buffer[ix++];
  185. }
  186.  
  187. phoneme_str_to_audio(cp)
  188.     char           *cp;
  189. {
  190.     register        i;
  191.     AuEventHandlerRec    *Rec;
  192.  
  193.     while (*cp)
  194.         if (isspace(*cp))
  195.         {
  196.             cp++;
  197.             speak_delay(0);
  198.         }
  199.         else
  200.         {
  201.             i = ch_to_code(&cp);
  202. #ifdef USE_PLAYDATA
  203.             Rec = AuSoundPlayFromData(aud, phoneme[i].sound_hdr,
  204.                 phoneme[i].data, AuNone, volume, (void (*))0,
  205.                 (void *)0, (AuFlowID *)0, (int *)0, (int *)0,
  206.                 (AuStatus *)0);
  207. #else
  208.             AuSoundPlaySynchronousFromFile(aud, phoneme[i].fname, volume);
  209. #endif
  210.                 
  211.         }
  212. }
  213.  
  214. /************************************************************************
  215. *                                    *
  216. *    ch_to_code                            *
  217. *    code_to_ch                            *
  218. *                                    *
  219. *    Map a phoneme name to a unique index between 1 and 1023, or    *
  220. *    vice versa.  Ch_to_code advances it's argument to the next    *
  221. *    phoneme (or null).  Code_to_ch returns a null-terminated    *
  222. *    string.                                *
  223. *                                    *
  224. ************************************************************************/
  225. int
  226. ch_to_code(cp)
  227.     char          **cp;
  228. {
  229.     register char  *tp = *cp;
  230.  
  231.     if (islower(*tp))
  232.     {
  233.         *cp += 1;
  234.         return *tp - 'a' + 1;
  235.     }
  236.     else
  237.     {
  238.         *cp += 2;
  239.         return ((*tp - 'A' + 1) << 5) | (*(tp + 1) - 'A' + 1);
  240.     }
  241. }
  242.  
  243. char           *
  244. code_to_ch(code)
  245.     int             code;
  246. {
  247.     static char     ch[3];
  248.  
  249.     if (code < (1 << 5))
  250.     {
  251.         ch[1] = code + 'a' - 1;
  252.         return &ch[1];
  253.     }
  254.     else
  255.     {
  256.         ch[0] = (code >> 5) + 'A' - 1;
  257.         ch[1] = (code & 0x1f) + 'A' - 1;
  258.         return &ch[0];
  259.     }
  260. }
  261.  
  262. /************************************************************************
  263. *                                    *
  264. *    speak_delay                            *
  265. *                                    *
  266. *    Flush the audio device and pause for the given interval.    *
  267. *    If no interval is specified, pause for 2/10 second.        *
  268. *                                    *
  269. ************************************************************************/
  270. speak_delay(delay)
  271.     int             delay;    /* in 10ths of a second */
  272. {
  273.     static struct timeval tv = {0, 200000};    /* 1sec == 1000000 usec */
  274.  
  275.     if (delay)
  276.         tv.tv_usec = delay * 100000;
  277.     (void) AuFlush(aud);
  278.     (void) select(0, 0, 0, 0, &tv);
  279.  
  280.     return 0;
  281. }
  282.  
  283. int
  284. fatal(code, str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  285.     int             code;
  286.     char           *str;
  287.     int             a1, a2, a3, a4, a5, a6, a7, a8, a9;
  288. {
  289.     char           *bp;
  290.     char            b1[256], b2[256];
  291.  
  292.     bp = (char *) sprintf(b1, str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  293. #if 0
  294.     if (code)
  295.         switch (code)
  296.         {
  297.         case AUDIO_UNIXERROR:
  298.             bp = (char *) sprintf(b2, "%s: %s", str, sys_errlist[errno]);
  299.             break;
  300.         case AUDIO_ERR_BADHDR:
  301.             bp = (char *) sprintf(b2, "%s: bad audio header", str);
  302.             break;
  303.         case AUDIO_ERR_BADFILEHDR:
  304.             bp = (char *) sprintf(b2, "%s: bad file header", str);
  305.             break;
  306.         case AUDIO_ERR_BADARG:
  307.             bp = (char *) sprintf(b2, "%s: bad subroutine argument", str);
  308.             break;
  309.         case AUDIO_ERR_NOEFFECT:
  310.             bp = (char *) sprintf(b2, "%s: device control ingnored", str);
  311.             break;
  312.         case AUDIO_ERR_ENCODING:
  313.             bp = (char *) sprintf(b2, "%s: unknown encoding format", str);
  314.             break;
  315.         case AUDIO_ERR_INTERRUPTED:
  316.             bp = (char *) sprintf(b2, "%s: operation was interrupted", str);
  317.             break;
  318.         default:
  319.             bp = (char *) sprintf(b2, "%s: <unknown error code>", str);
  320.             break;
  321.         }
  322. #endif
  323.  
  324.     fprintf(stderr, "%s\n", bp);
  325.  
  326.     return -1;
  327. }
  328.